package liveSimBE;

public class MOSFET {
	private double Vg, Vs, Vd;
	private double factor = 20e-6; // mu*Cox*W/L
	private double lambda;

	private double Vth;
	private boolean isNmos;

	public MOSFET(boolean isNmos) {
		this.isNmos = isNmos;
		if (isNmos) {
			Vth = .5;
			lambda = 1.0/20.0;
		} else {
			Vth = -.5;
			lambda = -1.0/20.0;
		}
	}

	public FETOperatingRegion getRegion() {
		if (isNmos) {
			double Vgs = Vg - Vs;
			double Vds = Vd - Vs;
			if (Vgs < Vth)
				return FETOperatingRegion.SubThreshold;
			if (Vds < Vgs-Vth)
				return FETOperatingRegion.Linear;
			else //if (Vds > Vgs-Vth)
				return FETOperatingRegion.Saturation;
		} else {
			// pmos
			double Vsg = Vs - Vg;
			double Vsd = Vd - Vg;
			if (Vsg < Math.abs(Vth))
				return FETOperatingRegion.SubThreshold;
			if (Vsd < Vsg-Math.abs(Vth))
				return FETOperatingRegion.Linear;
			else //if (Vsd > Vsg-Math.abs(Vth))
				return FETOperatingRegion.Saturation;			
		}
	}

	public double getId() {
//		if (isNmos) {
			double Vgs = Vg - Vs;
			double Vds = Vd - Vs;
			
			switch(getRegion()) {
			case SubThreshold:
				return 0; // approximate cut-off
			case Linear:
				return factor*((Vgs-Vth)*Vds - Vds*Vds/2);
			case Saturation:
				return factor/2*Math.pow(Vgs-Vth, 2)*(1+lambda*Vds);
			default:
				throw new AssertionError("Unknown region: " + getRegion());
			}
/*		} else {
			double Vsg = Vs - Vg;
			double Vsd = Vs - Vd;
			double absVth = Math.abs(Vth);

			switch(getRegion()) {
			case SubThreshold:
				return 0; // approximate cut-off
			case Linear:
				return factor*((Vsg-absVth)*Vsd-Vsd*Vsd/2);
			case Saturation:
				return factor/2*Math.pow(Vsg-absVth,2)*(1-lambda*Vsd);
			default:
				throw new AssertionError("Unknown region: " + getRegion());
			}
		}*/
	}

	public double getVd() {
		return Vd;
	}


	public void setVd(double vd) {
		Vd = vd;
	}


	public double getVg() {
		return Vg;
	}


	public void setVg(double vg) {
		Vg = vg;
	}


	public double getVs() {
		return Vs;
	}


	public void setVs(double vs) {
		Vs = vs;
	}
}
